#include <iostream>
#include <fstream>
#include "../utils/message.h"
#include "../utils/thread.h"
#include "submission.h"
#include <sys/wait.h>
#include <sys/signal.h>
#include <cstdlib>
#include <cstdio>
#include <assert.h>
#include <ctime>
#include "worker.h"
#include "balancer.h"

using namespace std;

MessageChannel* channel;
SubmissionMessage *message;
string path;
ofstream logFile;
int channelId;
int messageType;

//int nWorker;
//NewWorker* workers[20];

/*void initWorker(int nWorker , ofstream& pLogger) {
	for (int i = 0 ; i < nWorker ; i++) {
		workers[i] = new NewWorker(channel , &pLogger , messageType + i + 1);
		workers[i]->start();
		
		/*char systemCommand[200];
		sprintf(systemCommand , "%s evaluate queue %d %d > /var/log/worker-%d.log" , path.c_str() , channelId , messageType + i + 1 , i);
		
		system(systemCommand);
		
		pid_t pid = fork();
		
		if (pid == 0) {
			char sChannel[100], sMsgType[100];
			
			sprintf(sChannel , "%d" , channelId);
			sprintf(sMsgType , "%d" , messageType + i + 1);
			
			execl(path.c_str() , "yiic" , "evaluate" , "queue" , sChannel , sMsgType , (char*) 0);
			exit(0);
		}
		else {
		}
	}
}*/

void sighandler(int signum) {
	logFile << getCurrentDate() << " Stopping balancer with pid: " << getpid() << endl;
	
	if (signum == SIGINT)
		exit(0);
}

int main(int argc , char** argv) {
	assert(argc == 3);
	
	char pidFileName[100];
	
	sprintf(pidFileName , "/etc/balancer-%s.pid" , argv[2]);
	
	ofstream fout(pidFileName);
	fout << getpid() << endl;
	fout.close();
	
	AppBalancer* app = AppBalancer::createInstance(argv[1]);
	
	app->start();
	
	app->run();
	
	return 0;
}

/**
///Init
	signal(SIGKILL , sighandler);
	signal(SIGINT , sighandler);
	path = string(argv[1]);
	nWorker = atoi(argv[2]);
	channelId = atoi(argv[4]);
	messageType = atoi(argv[5]);
	
	///Create channel object
	channel = new MessageChannel(channelId);
	
	///Init file
	logFile.open(argv[3] , ios_base::app);
	
	///Init worker
	initWorker(nWorker , logFile);
	
	cout << "PID : " << getpid() << endl;
	logFile << getCurrentDate() << " Starting balancer with pid: " << getpid() << endl;
	
	message = new SubmissionMessage(messageType);
	
	while(1) {
		if (channel->receive(message , message->getLength()) >= 0) { ///GOT!
			logFile << getCurrentDate() << " Subs#" << message->getSubmissionId() << " received" << endl;
			bool found = false;
			int foundWorker;
			
			while (!found) {
				for (int i = 0 ; i < nWorker && !found ; i++) {
					if (!workers[i]->isBusy()) {
						found = true;
						foundWorker = i;
					}
				}
			}
			
			///Dispatch
			cout << "Dispatching subs#" << message->getSubmissionId() << " to worker #" << foundWorker << " by : " << getpid() << endl;
			
			logFile << getCurrentDate() << " Subs#" << message->getSubmissionId() << " dispatched to worker #" << foundWorker << " by : " << getpid() << endl;
			workers[foundWorker]->dispatch(message->getSubmissionId());
		}
		/*else
			usleep(1000);
	}
	
	delete message;
	delete channel;
	
	for (int i = 0 ; i < nWorker ; i++) {
		delete workers[i];
	}
*/

/***
 * TODO:
 * - Queue management from POSIX Message Queue
 * - Grading failure handling
 * - Parameterization
 * - Dashboard
 * */
